
/*
 * Copyright (c) 2022 boxbot team
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_connect.h"
#include "lwip/sockets.h"

#include "oc_mqtt.h"
#include "E53_IA1.h"

#include "wifiiot_pwm.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"



#define PWM_TASK_STACK_SIZE 512
#define PWM_TASK_PRIO 25

#define MSGQUEUE_OBJECTS 16 // number of Message Queue Objects
int count1=0;

typedef struct
{ // object data type
    char *Buf;
    uint8_t Idx;
} MSGQUEUE_OBJ_t;

MSGQUEUE_OBJ_t msg;
osMessageQueueId_t mid_MsgQueue; // message queue id

#define CLIENT_ID "62ff7f875f266f255bbbfa91_20220728_0_0_2022081912"
#define USERNAME "62ff7f875f266f255bbbfa91_20220728"
#define PASSWORD "60842594f5f2c64928b1e478e16ccb710af32ab4c56ce8ba09fcd3094cc868a0"

typedef enum
{
    en_msg_cmd = 0,
    en_msg_report,
} en_msg_type_t;

typedef struct
{
    char *request_id;
    char *payload;
} cmd_t;

typedef struct
{
    int lum;
    int temp;
    int hum;
} report_t;

typedef struct
{
    en_msg_type_t msg_type;
    union
    {
        cmd_t cmd;
        report_t report;
    } msg;
} app_msg_t;

typedef struct
{
    int connected;
    int led;
    int motor;
} app_cb_t;
static app_cb_t g_app_cb;

static const uint16_t g_tuneFreqs[]={
    0,
    
    38223, // 1 1046.5,-
    34052, // 2 1174.7,--
    30338, // 3 1318.5,--
    28635, // 4 1396.4,--
    25511, // 5 1568,---
    22728, // 6 1760,---
    20249, // 7 1975.5,---  
    51021,//  8,5_低音 783.99,   40M=40*1000*1000, 40M/783.99=51021
    45454,//  9,6_     880.00
    40495,//  10,7_     987.77    
    
};
static const uint8_t g_scoreNotes[] = {
    // 《两只老虎》简谱
    1, 2, 3, 1,    1, 2, 3, 1,   3, 4, 5,  3, 4, 5,
    5, 6, 5, 4, 3, 1,  5, 6, 5, 4, 3, 1,   1, 8, 1,  1, 8, 1,
};
static const uint8_t g_scoreNotes_txwtech[] = {
    // 《涛声依旧》简谱
    6,6,3,5,  6,5,5,
    1,2,3,3,  3,5,6,5,3,2,3,0,
    6,5,3,5, 1, 9,8,8,
    9,1,2,2,   2,6,3,      5,6,5,
   
    
 
};
 
// 曲谱时值
static const uint8_t g_scoreDurations[] = {
    4, 4, 4, 4,    4, 4, 4, 4,   4, 4, 8,  4, 4, 8,
    3, 1, 3, 1, 4, 4,  3, 1, 3, 1, 4, 4,   4, 4, 8,  4, 4, 8,
};
//txwtech
static const uint8_t g_scoreDurations_txwtech[] = {
    4, 4, 4, 4,  2,2,4,    
    2, 2, 4, 4,   2, 4, 1, 1, 2,2, 8,1,
    4,4,2,2,     4, 2, 2, 4,
    2,2,4,4,       2,4, 2,    2, 2, 8,
};

static void deal_report_msg(report_t *report)
{
    oc_mqtt_profile_service_t service;
    oc_mqtt_profile_kv_t temperature;
    oc_mqtt_profile_kv_t humidity;
    oc_mqtt_profile_kv_t luminance;
    oc_mqtt_profile_kv_t led;
    oc_mqtt_profile_kv_t motor;

    service.event_time = NULL;
    service.service_id = "Agriculture";
    service.service_property = &temperature;
    service.nxt = NULL;

    temperature.key = "Temperature";
    temperature.value = &report->temp;
    temperature.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    temperature.nxt = &humidity;

    led.key = "LightStatus";
    led.value = g_app_cb.led ? "ON" : "OFF";
    led.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    led.nxt = &motor;

    motor.key = "MotorStatus";
    motor.value = g_app_cb.motor ? "ON" : "OFF";
    motor.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    motor.nxt = NULL;

    oc_mqtt_profile_propertyreport(USERNAME, &service);
    return;
}

void oc_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
    app_msg_t *app_msg;

    int ret = 0;
    app_msg = malloc(sizeof(app_msg_t));
    app_msg->msg_type = en_msg_cmd;
    app_msg->msg.cmd.payload = (char *)recv_data;

    printf("recv data is %.*s\n", recv_size, recv_data);
    ret = osMessageQueuePut(mid_MsgQueue, &app_msg, 0U, 0U);
    if (ret != 0)
    {
        free(recv_data);
    }
    *resp_data = NULL;
    *resp_size = 0;
}

///< COMMAND DEAL
#include <cJSON.h>
static void deal_cmd_msg(cmd_t *cmd)
{
    cJSON *obj_root;
    cJSON *obj_cmdname;
    cJSON *obj_paras;
    cJSON *obj_para;

    int cmdret = 1;
    oc_mqtt_profile_cmdresp_t cmdresp;
    obj_root = cJSON_Parse(cmd->payload);
    if (NULL == obj_root)
    {
        goto EXIT_JSONPARSE;
    }

    obj_cmdname = cJSON_GetObjectItem(obj_root, "command_name");
    if (NULL == obj_cmdname)
    {
        goto EXIT_CMDOBJ;
    }
    if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Agriculture_Control_light"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Light");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }
        ///< operate the LED here
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.led = 1;
            Light_StatusSet(ON);
            printf("Light On!");
        }
        else
        {
            g_app_cb.led = 0;
            Light_StatusSet(OFF);
            printf("Light Off!");
        }
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Agriculture_Control_Motor"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Motor");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }
        ///< operate the Motor here
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.motor = 1;
            Motor_StatusSet(ON);
            printf("Motor On!");
        }
        else
        {
            g_app_cb.motor = 0;
            Motor_StatusSet(OFF);
            printf("Motor Off!");
        }
        cmdret = 0;
    }

EXIT_OBJPARA:
EXIT_OBJPARAS:
EXIT_CMDOBJ:
    cJSON_Delete(obj_root);
EXIT_JSONPARSE:
    ///< do the response
    cmdresp.paras = NULL;
    cmdresp.request_id = cmd->request_id;
    cmdresp.ret_code = cmdret;
    cmdresp.ret_name = NULL;
    (void)oc_mqtt_profile_cmdresp(NULL, &cmdresp);
    return;
}

static int task_main_entry(void)
{
    app_msg_t *app_msg;

    uint32_t ret = WifiConnect("XH", "00000000");

    device_info_init(CLIENT_ID, USERNAME, PASSWORD);
    oc_mqtt_init();
    oc_set_cmd_rsp_cb(oc_cmd_rsp_cb);

    while (1)
    {
        app_msg = NULL;
        (void)osMessageQueueGet(mid_MsgQueue, (void **)&app_msg, NULL, 0U);
        if (NULL != app_msg)
        {
            switch (app_msg->msg_type)
            {
            case en_msg_cmd:
                deal_cmd_msg(&app_msg->msg.cmd);
                
 
    uint32_t tune;
    uint16_t freqDivisor;
    uint32_t tuneInterval;
   GpioInit();
   IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12,WIFI_IOT_IO_FUNC_GPIO_12_PWM3_OUT);  
  // 
   
   PwmInit(WIFI_IOT_PWM_PORT_PWM3); 
  //  hi_pwm_set_clock(PWM_CLK_160M);   
//    PwmSetClock(WIFI_IOT_PWM_CLK_XTAL);  
   //while(1)
   {
    
       WifiIotGpioValue val=WIFI_IOT_GPIO_VALUE0;
       GpioGetOutputVal(WIFI_IOT_IO_NAME_GPIO_12,&val);
        count1=sizeof(g_tuneFreqs)/sizeof(g_tuneFreqs[0]);
       printf("count is:  %d\n",count1);
       
 
       printf("execute pwm,value: %d\n",val);
       if(0)
       {
         for(size_t i=0;i<sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]);i++)
          {
            tune=g_scoreNotes[i];//简谱标记
            freqDivisor=g_tuneFreqs[tune];//对应的频率
            tuneInterval=g_scoreDurations[i]*(125 * 1000);//声音的延迟
            PwmStart(WIFI_IOT_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
          //osDelay(tuneInterval);
            osDelay(tuneInterval);
            PwmStop(WIFI_IOT_PWM_PORT_PWM3);
          }
       }
 
       if(1)
       {
        for(size_t i=0;i<sizeof(g_scoreNotes_txwtech)/sizeof(g_scoreNotes_txwtech[0]);i++)
        {
           tune=g_scoreNotes_txwtech[i];//简谱标记---
           freqDivisor=g_tuneFreqs[tune];//对应的频率
           tuneInterval=g_scoreDurations_txwtech[i]*(125 * 1000);//声音的延迟---
          PwmStart(WIFI_IOT_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
          
          osDelay(tuneInterval);
          PwmStop(WIFI_IOT_PWM_PORT_PWM3);
         }
       }
 
 
       //验证音准
      // for(size_t i=0;i<sizeof(g_tuneFreqs)/sizeof(g_tuneFreqs[0]);i++)
      //  {
          // tune=g_tuneFreqs[i];//简谱标记---
         // freqDivisor=tune;
         // hi_pwm_start(HI_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
          
         // hi_udelay(3*125 * 1000);
         // hi_pwm_stop(HI_PWM_PORT_PWM3);
        // }
    }
                break;
            case en_msg_report:
                deal_report_msg(&app_msg->msg.report);
                break;
            default:
                break;
            }
            free(app_msg);
        }
    }
    return 0;
}

static int task_sensor_entry(void)
{
    app_msg_t *app_msg;
    E53_IA1_Data_TypeDef data;
    E53_IA1_Init();
    while (1)
    {
        E53_IA1_Read_Data(&data);
        app_msg = malloc(sizeof(app_msg_t));
        printf("SENSOR:lum:%.2f temp:%.2f hum:%.2f\r\n", data.Lux, data.Temperature, data.Humidity);
        if (NULL != app_msg)
        {
            app_msg->msg_type = en_msg_report;
            app_msg->msg.report.hum = (int)data.Humidity;
            app_msg->msg.report.lum = (int)data.Lux;
            app_msg->msg.report.temp = (int)data.Temperature;
        
            if (0 != osMessageQueuePut(mid_MsgQueue, &app_msg, 0U, 0U))
            {
                free(app_msg);
            }
        }
        sleep(3);
    }
    return 0;
}

// static void GpioTask(void *arg)
// {
//     (void) arg;
 
//     uint32_t tune;
//     uint16_t freqDivisor;
//     uint32_t tuneInterval;
//    GpioInit();
//    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12,WIFI_IOT_IO_FUNC_GPIO_12_PWM3_OUT);  
//   // 
   
//    PwmInit(WIFI_IOT_PWM_PORT_PWM3); 
//   //  hi_pwm_set_clock(PWM_CLK_160M);   
//    PwmSetClock(WIFI_IOT_PWM_CLK_XTAL);  
//    //while(1)
//    {
    
//        WifiIotGpioValue val=WIFI_IOT_GPIO_VALUE0;
//        IoTGpioGetOutputVal(WIFI_IOT_IO_NAME_GPIO_12,&val);
//         count1=sizeof(g_tuneFreqs)/sizeof(g_tuneFreqs[0]);
//        printf("count is:  %d\n",count1);
       
 
//        printf("execute pwm,value: %d\n",val);
//        if(0)
//        {
//          for(size_t i=0;i<sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]);i++)
//           {
//             tune=g_scoreNotes[i];//简谱标记
//             freqDivisor=g_tuneFreqs[tune];//对应的频率
//             tuneInterval=g_scoreDurations[i]*(125 * 1000);//声音的延迟
//             PwmStart(WIFI_IOT_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
//           //osDelay(tuneInterval);
//             osDelay(tuneInterval);
//             PwmStop(WIFI_IOT_PWM_PORT_PWM3);
//           }
//        }
 
//        if(1)
//        {
//         for(size_t i=0;i<sizeof(g_scoreNotes_txwtech)/sizeof(g_scoreNotes_txwtech[0]);i++)
//         {
//            tune=g_scoreNotes_txwtech[i];//简谱标记---
//            freqDivisor=g_tuneFreqs[tune];//对应的频率
//            tuneInterval=g_scoreDurations_txwtech[i]*(125 * 1000);//声音的延迟---
//           PwmStart(WIFI_IOT_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
          
//           osDelay(tuneInterval);
//           PwmStop(WIFI_IOT_PWM_PORT_PWM3);
//          }
//        }
 
 
//        //验证音准
//       // for(size_t i=0;i<sizeof(g_tuneFreqs)/sizeof(g_tuneFreqs[0]);i++)
//       //  {
//           // tune=g_tuneFreqs[i];//简谱标记---
//          // freqDivisor=tune;
//          // hi_pwm_start(HI_PWM_PORT_PWM3,freqDivisor/2,freqDivisor);
          
//          // hi_udelay(3*125 * 1000);
//          // hi_pwm_stop(HI_PWM_PORT_PWM3);
//         // }
//     }
// }
static void OC_Demo(void)
{
    mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, 10, NULL);
    if (mid_MsgQueue == NULL)
    {
        printf("Falied to create Message Queue!\n");
    }

    osThreadAttr_t attr;

    attr.name = "task_main_entry";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)task_main_entry, NULL, &attr) == NULL)
    {
        printf("Falied to create task_main_entry!\n");
    }
    attr.stack_size = 2048;
    attr.priority = 25;
    attr.name = "task_sensor_entry";
    if (osThreadNew((osThreadFunc_t)task_sensor_entry, NULL, &attr) == NULL)
    {
        printf("Falied to create task_sensor_entry!\n");
    }
}

APP_FEATURE_INIT(OC_Demo);
